﻿/*
 * ========================================================================
 * Copyright(c) 2007-2012 情留メ蚊子, All Rights Reserved.
 * Welcom use the LiteFetion.
 * See more information,Please goto http://www.94qing.com
 * ========================================================================
 * 
 * 作 者：情留メ蚊子
 * Q  Q: 540644769
 * 邮 箱：qlwz@qq.com
 * 网 址：http://www.94qing.com
 * ========================================================================
*/
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.IO.Compression;
using System.Net;
using System.Text;

namespace LiteFetion
{
    /// <summary>
    /// 访问模式
    /// </summary>
    public enum Method
    {
        /// <summary>
        ///  POST
        /// </summary>
        POST,
        /// <summary>
        /// GET
        /// </summary>
        GET
    }

    public class HttpHelper
    {
        /// <summary>
        /// HttpHelper
        /// </summary>
        public HttpHelper()
        {
            Cookies = new List<Cookie>();
            Url = string.Empty;
            PostData = string.Empty;
            Referer = string.Empty;
            Method = Method.GET;
            Html = string.Empty;
            ErrMsg = string.Empty;
            Encoding = Encoding.GetEncoding("UTF-8");
            ContentType = "application/x-www-form-urlencoded";
            UserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.10) Gecko/20100914 Firefox/3.6.10 (.NET CLR 3.5.30729)";
            Accept = "text/html,application/xhtml+xml,application/xml,image/png,image/*;q=0.9,*/*;q=0.8";

        }

        public static void SetHeaderValue(WebHeaderCollection header, string name, string value)
        {
            var property = typeof(WebHeaderCollection).GetProperty("InnerCollection",
                System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
            if (property != null)
            {
                var collection = property.GetValue(header, null) as NameValueCollection;
                collection[name] = value;
            }
        }

        public bool Do()
        {
            HttpWebRequest httpWebRequest = null;
            HttpWebResponse httpWebResponse = null;
            try
            {
                httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(Url);
                httpWebRequest.CookieContainer = CookieContainer;
                if (!Referer.IsEmpty())
                {
                    httpWebRequest.Referer = Referer;
                }
                httpWebRequest.Accept = Accept;
                if (!AcceptLanguage.IsEmpty())
                {
                    httpWebRequest.Headers[HttpRequestHeader.AcceptLanguage] = AcceptLanguage;
                }
                if (!AcceptEncoding.IsEmpty())
                {
                    httpWebRequest.Headers[HttpRequestHeader.AcceptEncoding] = AcceptEncoding;
                }
                if (KeepAlive)
                {
                    SetHeaderValue(httpWebRequest.Headers, "Connection", "Keep-Alive");
                }
                //httpWebRequest.KeepAlive = KeepAlive;
                httpWebRequest.UserAgent = UserAgent;
                httpWebRequest.Method = Enum.GetName(typeof(Method), Method);
                httpWebRequest.ServicePoint.Expect100Continue = false;
                httpWebRequest.AllowAutoRedirect = AllowAutoRedirect;
                if (Method == Method.POST && !string.IsNullOrEmpty(PostData))
                {
                    httpWebRequest.ContentType = ContentType;
                    byte[] byteRequest = Encoding.GetBytes(PostData);
                    httpWebRequest.ContentLength = byteRequest.Length;
                    Stream stream = httpWebRequest.GetRequestStream();
                    stream.Write(byteRequest, 0, byteRequest.Length);
                    stream.Close();
                }

                httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();
                StreamReader streamReader = null;
                if (httpWebResponse.ContentEncoding != null && httpWebResponse.ContentEncoding.Equals("gzip", StringComparison.InvariantCultureIgnoreCase))
                {
                    using (streamReader = new StreamReader(new GZipStream(httpWebResponse.GetResponseStream(), CompressionMode.Decompress), Encoding))
                    {
                        Html = streamReader.ReadToEnd();
                    }
                }
                else
                {
                    using (streamReader = new StreamReader(httpWebResponse.GetResponseStream(), Encoding))
                    {
                        Html = streamReader.ReadToEnd();
                    }
                }
                StatusCode = httpWebResponse.StatusCode;

                foreach (Cookie cookie in httpWebResponse.Cookies)
                {
                    if (Cookies.Find(p => p.Name == cookie.Name) != null)
                    {
                        Cookies.RemoveAll(p => p.Name == cookie.Name);
                    }
                    Cookies.Add(cookie);
                }
                return true;
            }
            catch (Exception e)
            {
                ErrMsg = e.Message;
                return false;
            }
            finally
            {
                if (httpWebRequest != null)
                {
                    httpWebRequest.Abort();
                }
                if (httpWebResponse != null)
                {
                    httpWebResponse.Close();
                }
            }
        }

        /// <summary>
        /// 获取字符流
        /// </summary>
        public byte[] GetStream()
        {
            HttpWebRequest httpWebRequest = null;
            HttpWebResponse httpWebResponse = null;

            try
            {
                httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(Url);
                httpWebRequest.ContentType = ContentType;
                httpWebRequest.CookieContainer = CookieContainer;
                if (!Referer.IsEmpty())
                {
                    httpWebRequest.Referer = Referer;
                }
                httpWebRequest.Accept = Accept;
                httpWebRequest.UserAgent = UserAgent;
                httpWebRequest.Method = Enum.GetName(typeof(Method), Method);
                httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse();

                if (PostData.Length > 0)
                {
                    SaveBinaryFile(httpWebResponse, PostData);
                }

                foreach (Cookie cookie in httpWebResponse.Cookies)
                {
                    if (Cookies.Find(p => p.Name == cookie.Name) != null)
                    {
                        Cookies.RemoveAll(p => p.Name == cookie.Name);
                    }
                    Cookies.Add(cookie);
                }

                Stream getStream = httpWebResponse.GetResponseStream();
                long contentLength = httpWebResponse.ContentLength;

                byte[] outBytes = new byte[contentLength];
                outBytes = HttpHelper.ReadFully(getStream);
                getStream.Close();
                return outBytes;
            }
            catch (Exception e)
            {
                ErrMsg = e.Message;
                return null;
            }
            finally
            {
                if (httpWebRequest != null)
                {
                    httpWebRequest.Abort();
                }
                if (httpWebResponse != null)
                {
                    httpWebResponse.Close();
                }
            }
        }

        public static byte[] ReadFully(Stream stream)
        {
            byte[] buffer = new byte[128];
            using (MemoryStream ms = new MemoryStream())
            {
                while (true)
                {
                    int read = stream.Read(buffer, 0, buffer.Length);
                    if (read <= 0)
                        return ms.ToArray();
                    ms.Write(buffer, 0, read);
                }
            }
        }

        private static bool SaveBinaryFile(WebResponse response, string savePath)
        {
            bool value = false;
            byte[] buffer = new byte[1024];
            Stream outStream = null;
            Stream inStream = null;
            try
            {
                if (File.Exists(savePath))
                {
                    File.Delete(savePath);
                }
                outStream = System.IO.File.Create(savePath);
                inStream = response.GetResponseStream();
                int l;
                do
                {
                    l = inStream.Read(buffer, 0, buffer.Length);
                    if (l > 0)
                    {
                        outStream.Write(buffer, 0, l);
                    }
                } while (l > 0);
                value = true;
            }
            finally
            {
                if (outStream != null)
                {
                    outStream.Close();
                }
                if (inStream != null)
                {
                    inStream.Close();
                }
            }
            return value;
        }

        /// <summary>
        /// Cookies
        /// </summary>
        public List<Cookie> Cookies { get; set; }

        /// <summary>
        /// CookieContainer
        /// </summary>
        private CookieContainer CookieContainer
        {
            get
            {
                string domain = new Uri(Url).Host;
                CookieContainer cc = new CookieContainer();
                string _cookies = string.Empty;
                foreach (Cookie c in Cookies)
                {
                    c.Domain = domain;
                    cc.Add(c);
                }
                return cc;
            }
        }

        /// <summary>
        /// 状态码
        /// </summary>
        public HttpStatusCode StatusCode { get; set; }

        /// <summary>
        /// 是否跳转后的页面
        /// </summary>
        public bool AllowAutoRedirect { get; set; }

        /// <summary>
        /// Url
        /// </summary>
        public string Url { get; set; }

        /// <summary>
        /// Referer
        /// </summary>
        public string Referer { get; set; }

        /// <summary>
        /// Accept
        /// </summary>
        public string Accept { get; set; }

        /// <summary>
        /// AcceptEncoding 'gzip, deflate
        /// </summary>
        public string AcceptEncoding { get; set; }

        /// <summary>
        /// AcceptLanguage  'zh-CN
        /// </summary>
        public string AcceptLanguage { get; set; }

        /// <summary>
        /// ContentType
        /// </summary>
        public string ContentType { get; set; }

        /// <summary>
        /// KeepAlive
        /// </summary>
        public bool KeepAlive { get; set; }

        /// <summary>
        /// UserAgent
        /// </summary>
        public string UserAgent { get; set; }

        /// <summary>
        /// 发送数据
        /// </summary>
        public string PostData { get; set; }

        /// <summary>
        /// 模式
        /// </summary>
        public Method Method { get; set; }

        /// <summary>
        /// 编码
        /// </summary>
        public Encoding Encoding { get; set; }

        /// <summary>
        /// 获取错误
        /// </summary>
        public string ErrMsg { get; set; }

        /// <summary>
        /// 获取结果
        /// </summary>
        public string Html { get; set; }
    }
}
